/////////////////////////////////////////////     File     //////////////////////////////////////////////////
// Author: James Chen
// Filename: Input.h
// Created: Tuesday, August 10, 2010 3:27:56 PM
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once

//	The version of DirectInput to use.
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
#include <vector>
using std::vector;

#pragma comment (lib, "dinput8.lib")
#pragma comment (lib, "dxguid.lib")
#pragma warning (disable : 4996)

//	Macro to safely Release COM Objects.
#ifndef SAFE_RELEASE
#define SAFE_RELEASE(p)		if (p) { p->Release(); p = NULL; }
#endif

//	MessageBox for Errors that occur within DirectInput.
#ifndef DIERRBOX
#define DIERRBOX(a)	{ MessageBox(m_hWnd, LPCWSTR(a), LPCWSTR("CInput Error"), MB_OK | MB_ICONEXCLAMATION); return false; }
#endif

typedef unsigned char UCHAR;
typedef unsigned char BYTE;

//	Defines for the Mouse.
enum MouseAxises  { XAXIS = 1, YAXIS, ZAXIS, };
enum MouseButtons { M_BUTTON_LEFT = 0, M_BUTTON_RIGHT, M_BUTTON_MIDDLE, M_BUTTON_BACK, };

#define BUFFER_SIZE 10										//	Arbitrary number of buffer element for Buffered Input.

/////////////////////////////////////////////     Class     /////////////////////////////////////////////////
// Name: CInput
// Author: James Chen
// Created: Tuesday, August 10, 2010 3:27:56 PM
//
// Purpose: Input Device message handling
//
// Revisions: 
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CInput
{
	////////////////////// Singleton Implementation Begins //////////////////////
private:

	CInput(void);
	CInput(const CInput&);
	CInput& operator =(const CInput&);
	static CInput *m_pInstance;

public:

	virtual ~CInput(void);
	static CInput *GetInstance(void);
	static void DeleteInstance(void);
	/////////////////////// Singleton Implementation Ends ///////////////////////

private:
	LPDIRECTINPUT8		 m_lpDIObject;					//	Direct Input COM Object.
	LPDIRECTINPUTDEVICE8 m_lpDIKey;						//	Direct Input Device for the Keyboard.
	LPDIRECTINPUTDEVICE8 m_lpDIMouse;					//	Direct Input Device for the Mouse.
	DIDEVICEOBJECTDATA   m_didodKey[BUFFER_SIZE];		//	Receives buffered data for the Keyboard.
	DIDEVICEOBJECTDATA	 m_didodMouse[BUFFER_SIZE];		//	Receives buffered data for the Mouse.

	bool	  m_bExclusive;								//	Determines the cooperation level for the devices.
	char	  m_szBuffer[128];							//	For Error Tracking.
	HKL	 	  m_keyLayout;								//	The Keyboard Layout.
	HWND	  m_hWnd;									//	Main Window Handle.
	HINSTANCE m_hInstance;								//	Main Application Instance.

	UCHAR		  m_ucKeyState[256];					//	Holds Keyboard Data.
	bool		  m_bKeysPressed[256];					//	Used for BufferedKeyEx.
	BYTE		  m_ucAsciiVals[256];					//	Gonna hold the DAMN ascii value of a given key.
	DIMOUSESTATE2 m_diMouseState;						//	Holds Mouse	Data.
	bool		  m_bMouseButtons[8];					//	Used for OnMouseButtonRelease Method.
	DWORD		  m_dwKeyElements;						//	Number of Elements in the Buffer for the Keyboard.
	DWORD		  m_dwMouseElements;					//	Number of Elements in the Buffer for the Mouse.

public:

	
	bool InitDevices(HWND hWnd, HINSTANCE hMainInstance, bool bExclusive = false);

	bool InitKeyboard(HWND hWnd, HINSTANCE hMainInstance, bool bExclusive = false);
	bool InitMouse(HWND hWnd, HINSTANCE hMainInstance, bool bExclusive = false);

	void ShutdownDirectInput(void);

	bool ReadDevices(void);

	bool ReadKeyboard(void);
	bool ReadBufferedKeyboard(void);
	bool GetKey(UCHAR ucKey);
	char CheckKeys(void);
	char CheckBufferedKeys(void);
	bool GetBufferedKey(UCHAR ucKey);
	bool GetBufferedKeyEx(UCHAR ucKey);

	bool ReadMouse(void);
	bool ReadBufferedMouse(void);
	bool OnMouseButtonRelease(BYTE mButton);
	bool GetMouseButton(BYTE mButton);
	bool GetBufferedMouseButton(BYTE mButton);
	LONG GetMouseAxis(LONG lAxis);

};